﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Collections;
using System.ComponentModel;

namespace ProgNetComponents.Hosting
{
    /// <summary>
    /// HostObjectCollection
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class HostObjectCollection<T> : Collection<T>, IList<T>, IList, ITypedList where T : IStateObject, IHostObject
    {
        private static T instance;
        private static T Instance
        {
            get
            {
                if (instance == null)
                    instance = Activator.CreateInstance<T>();
                return instance;
            }
        }
        /// <summary>
        /// deleted items
        /// </summary>
        List<T> deleted = new List<T>();

        /// <summary>
        /// Removes the element at the specified index of the <see cref="T:System.Collections.ObjectModel.Collection`1" />.
        /// </summary>
        /// <param name="index">The zero-based index of the element to remove.</param>
        protected override void RemoveItem(int index)
        {
            T item = this[index];
            if (item.State != ObjectState.Added)
                item.State = ObjectState.Deleted;
            deleted.Add(item);

            base.RemoveItem(index);
        }
        /// <summary>
        /// Deletes all items.
        /// </summary>
        public void DeleteAll()
        {
            while (this.Count > 0)
                this.RemoveItem(0);
        }
        /// <summary>
        /// Removes all elements from the <see cref="T:System.Collections.ObjectModel.Collection`1" />.
        /// </summary>
        protected override void ClearItems()
        {
            base.ClearItems();
            deleted.Clear();
        }
        /// <summary>
        /// Gets the items with specified state.
        /// </summary>
        /// <param name="state">The state.</param>
        /// <returns></returns>
        public T[] GetItems(ObjectState state)
        {
            switch (state)
            {
                case ObjectState.Unchanged:
                case ObjectState.Added:
                case ObjectState.Modified:
                    return this.Where((s) => { return s.State == state; }).ToArray();
                case ObjectState.Deleted:
                    return deleted.ToArray();
                default:
                    return new T[0];
            }
        }
        /// <summary>
        /// Gets all items including deleted ones.
        /// </summary>
        /// <returns></returns>
        public T[] GetAllItems()
        {
            List<T> l = new List<T>();
            l.AddRange(this);
            l.AddRange(deleted);
            return l.ToArray();
        }

        /// <summary>
        /// Clears deleted items and sets State to Unchanged for all items in collection.
        /// </summary>
        public void Save()
        {
            deleted.Clear();
            foreach (var i in this)
                i.State = ObjectState.Unchanged;
        }

        /// <summary>
        /// Returns the <see cref="T:System.ComponentModel.PropertyDescriptorCollection" /> that represents the properties on each item used to bind data.
        /// </summary>
        /// <param name="listAccessors">An array of <see cref="T:System.ComponentModel.PropertyDescriptor" /> objects to find in the collection as bindable. This can be null.</param>
        /// <returns>
        /// The <see cref="T:System.ComponentModel.PropertyDescriptorCollection" /> that represents the properties on each item used to bind data.
        /// </returns>
        PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
        {
            return TypeDescriptor.GetProperties(Instance, false);
        }

        /// <summary>
        /// Returns the name of the list.
        /// </summary>
        /// <param name="listAccessors">An array of <see cref="T:System.ComponentModel.PropertyDescriptor" /> objects, for which the list name is returned. This can be null.</param>
        /// <returns>
        /// The name of the list.
        /// </returns>
        string ITypedList.GetListName(PropertyDescriptor[] listAccessors)
        {
            return null;
        }
    }
}
